﻿using AspNetCore.Host.Middleware;
using Microsoft.Extensions.DependencyInjection;

namespace AspNetCore.Host.Hosting
{
    public delegate Task RequestDelegate(HttpContext context);

    public interface IApplicationBuilder
    {
        void Use(Func<RequestDelegate, RequestDelegate> middleware);
    }

    public class ApplicationBuilder : IApplicationBuilder
    {
        private List<Func<RequestDelegate, RequestDelegate>> _middlewares = new();
        
        public void Use(Func<RequestDelegate, RequestDelegate> middleware)
        {
            _middlewares.Add(middleware);
        }

        public RequestDelegate Build()
        {
            RequestDelegate app = async context =>
            {
                await context.Response.WriteAsync("404");
            };
            for (int i = _middlewares.Count - 1; i > -1; i--)
            {
                app = _middlewares[i](app);
            }
            return app;
        }
    }
    public static class IApplicationBuilderExtensions
    {
        public static void Use(this IApplicationBuilder app, Func<HttpContext, Func<Task>, Task> middleware)
        {
            app.Use(next =>
            {
                return async context =>
                {
                    await middleware(context, async () => await next(context));
                };
            });
        }
       
        public static void Use<T>(this IApplicationBuilder app)
            where T : IMiddleware
        {
            app.Use(next => 
            {
                return async context => 
                {
                    var middleware = ActivatorUtilities.CreateInstance<T>(context.RequestServices, next);
                    await middleware.InvokeAsync(context);
                };
            });
        }
       
        public static void Run(this IApplicationBuilder app, RequestDelegate endpoint)
        {
            app.Use(_ =>
            {
                return async context =>
                {
                    await endpoint(context);
                };
            });
        }
    }
}
